home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 15 / Example 15.2 / unit.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-17  |  7.7 KB  |  332 lines

  1. #include "unit.h"
  2.  
  3. std::vector<SKINNEDMESH*> unitMeshes;
  4.  
  5. void LoadUnitResources(IDirect3DDevice9* m_pDevice)
  6. {
  7.     std::vector<std::string> fnames;
  8.  
  9.     fnames.push_back("units/drone.x");
  10.     fnames.push_back("units/soldier.x");
  11.     fnames.push_back("units/magician.x");
  12.  
  13.     for(int i=0;i<fnames.size();i++)
  14.     {
  15.         SKINNEDMESH *newMesh = new SKINNEDMESH();
  16.         newMesh->Load((char*)fnames[i].c_str(), m_pDevice);
  17.         unitMeshes.push_back(newMesh);
  18.     }
  19. }
  20.  
  21. void UnloadUnitResources()
  22. {
  23.     for(int i=0;i<unitMeshes.size();i++)
  24.         if(unitMeshes[i] != NULL)
  25.             delete unitMeshes[i];
  26.  
  27.     unitMeshes.clear();
  28. }
  29.  
  30. //////////////////////////////////////////////////////////////////////////////////
  31. //                                UNIT                                            //
  32. //////////////////////////////////////////////////////////////////////////////////
  33.  
  34. UNIT::UNIT(int _type, int _team, INTPOINT mp, TERRAIN *_terrain, IDirect3DDevice9* Dev) : MAPOBJECT()
  35. {
  36.     m_type = _type;
  37.     m_team = _team;
  38.     m_mappos = mp;
  39.     m_pTerrain = _terrain;
  40.     m_pDevice = Dev;
  41.     m_mapsize.Set(1, 1);
  42.     m_team = 0;
  43.     m_time = m_pauseTime = 0.0f;
  44.     m_animation = m_activeWP = 0;
  45.     m_rotation = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  46.     m_scale = D3DXVECTOR3(0.2f, 0.2f, 0.2f);
  47.     m_isBuilding = m_moving = false;
  48.     m_movePrc = 0.0f;
  49.  
  50.     if(m_pTerrain != NULL)
  51.     {
  52.         m_position = m_pTerrain->GetWorldPos(m_mappos);
  53.         MAPTILE *tile = m_pTerrain->GetTile(m_mappos);
  54.         if(tile != NULL)tile->m_pMapObject = this;
  55.     }
  56.     else m_position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  57.  
  58.     if(m_type == 0)        //Farmer
  59.     {
  60.         m_hp = m_hpMax = 100;
  61.         m_range = 1;
  62.         m_damage = 5;
  63.         m_sightRadius = 7;
  64.         m_speed = 1.0f;
  65.         m_name = "Farmer";
  66.     }    
  67.     else if(m_type == 1)        //Soldier
  68.     {
  69.         m_hp = m_hpMax = 180;
  70.         m_range = 1;
  71.         m_damage = 12;
  72.         m_sightRadius = 8;
  73.         m_speed = 0.8f;
  74.         m_name = "Soldier";
  75.     }    
  76.     else if(m_type == 2)        //Magician
  77.     {
  78.         m_hp = m_hpMax = 100;
  79.         m_range = 5;
  80.         m_damage = 8;
  81.         m_sightRadius = 10;
  82.         m_speed = 1.1f;
  83.         m_name = "Magician";
  84.     }    
  85.  
  86.     m_pAnimControl = unitMeshes[m_type]->GetAnimationControl();
  87.     if(m_pAnimControl != NULL)
  88.         m_pAnimControl->ResetTime();
  89.  
  90.     SetAnimation("Still");
  91. }
  92.  
  93. UNIT::~UNIT()
  94. {
  95.  
  96. }
  97.  
  98. void UNIT::Render()
  99. {
  100.     if(m_type < unitMeshes.size() && unitMeshes[m_type] != NULL)
  101.     {
  102.         SetAnimation(m_animation);
  103.  
  104.         unitMeshes[m_type]->SetPose(GetWorldMatrix(), m_pAnimControl, m_time);
  105.         unitMeshes[m_type]->Render(NULL);
  106.         m_time = 0.0f;
  107.     }
  108. }
  109.  
  110. void UNIT::Update(float deltaTime)
  111. {
  112.     //Pause the units...
  113.     if(m_pauseTime > 0.0f)
  114.     {
  115.         m_pauseTime -= deltaTime;
  116.         return;
  117.     }
  118.  
  119.     //update unit animation time
  120.     m_time += deltaTime * 0.8f * m_speed;
  121.  
  122.     //if the unit is moving...
  123.     if(m_moving)
  124.     {
  125.         if(m_movePrc < 1.0f)
  126.             m_movePrc += deltaTime * m_speed;
  127.  
  128.         //Next Waypoint
  129.         if(m_movePrc >= 1.0f)
  130.         {            
  131.             m_activeWP++;
  132.  
  133.             //Goal reached
  134.             if(m_activeWP >= m_path.size())
  135.             {
  136.                 m_moving = false;
  137.                 SetAnimation("Still");
  138.  
  139.                 if(m_mappos != m_finalGoal)
  140.                     MoveTo(m_finalGoal, false, true);
  141.  
  142.                 return;
  143.             }
  144.  
  145.             if(!CheckCollision(m_path[m_activeWP]))
  146.             {
  147.                 SetAnimation("Run");
  148.                 MoveUnit(m_path[m_activeWP]);
  149.             }
  150.             else return;
  151.         }
  152.  
  153.         //Interpolate position between m_lastWP and m_nextWP
  154.         m_position = m_lastWP * (1.0f - m_movePrc) + m_nextWP * m_movePrc;
  155.     }
  156. }
  157.  
  158. bool UNIT::CheckCollision(INTPOINT mp)
  159. {
  160.     MAPTILE *tile = m_pTerrain->GetTile(mp);
  161.     if(tile == NULL)return false;
  162.     
  163.     if(tile->m_pMapObject != NULL && tile->m_pMapObject != this)    //Collision with another unit
  164.     {
  165.         UNIT *otherUnit = (UNIT*)tile->m_pMapObject;
  166.  
  167.         if(otherUnit->m_moving && otherUnit->m_pauseTime <= 0.0f)        //The other unit is moving
  168.         {
  169.             //Pause the unit and wait for the other one to move 
  170.             Pause((100 + rand()%200) / 1000.0f);
  171.             if(m_activeWP > 0)m_activeWP--;            
  172.         }
  173.         else    //Recalculate path
  174.         {
  175.             //Find next unoccupied walkable tile
  176.             INTPOINT tempGoal = m_mappos;
  177.             for(int i=m_activeWP;i<m_path.size();i++)
  178.             {
  179.                 MAPTILE *tile = m_pTerrain->GetTile(m_path[i]);
  180.                 if(tile != NULL)
  181.                     if(tile->m_walkable && tile->m_pMapObject == NULL)
  182.                     {
  183.                         tempGoal = m_path[i];
  184.                         break;
  185.                     }
  186.             }
  187.  
  188.             //No available tile found 
  189.             if(tempGoal == m_mappos)
  190.             {
  191.                 //Move to tile closest to the original goal
  192.                 INTPOINT newGoal = m_pTerrain->GetClosestFreeTile(m_finalGoal, m_mappos);
  193.  
  194.                 if(newGoal == m_mappos || m_mappos.Distance(m_finalGoal) < 2.0f)
  195.                 {
  196.                     m_moving = false;
  197.                     SetAnimation("Still");
  198.                 }
  199.                 else MoveTo(newGoal, false, true);
  200.             }
  201.             else 
  202.             {
  203.                 //Move to tempGoal to avoid unit, then continue to finalGoal
  204.                 MoveTo(tempGoal, true, false); 
  205.             }
  206.         }
  207.  
  208.         return true;    //A Collision happened
  209.     }
  210.     
  211.     return false;        //No Collision
  212. }
  213.  
  214. void UNIT::Pause(float time)
  215. {
  216.     SetAnimation("Still");
  217.     m_pauseTime = time;
  218. }
  219.  
  220. BBOX UNIT::GetBoundingBox()
  221. {
  222.     if(m_type == 0)        //Farmer
  223.         return BBOX(m_position + D3DXVECTOR3(0.3f, 1.0f, 0.3f), m_position - D3DXVECTOR3(0.3f, 0.0f, 0.3f));
  224.     else if(m_type == 1)    //Soldier
  225.         return BBOX(m_position + D3DXVECTOR3(0.35f, 1.2f, 0.35f), m_position - D3DXVECTOR3(0.35f, 0.0f, 0.35f));
  226.     else if(m_type == 2)    //Magician
  227.         return BBOX(m_position + D3DXVECTOR3(0.3f, 1.1f, 0.3f), m_position - D3DXVECTOR3(0.3f, 0.0f, 0.3f));
  228. }
  229.  
  230. D3DXMATRIX UNIT::GetWorldMatrix()
  231. {
  232.     D3DXMATRIX s, p, r;
  233.     D3DXMatrixTranslation(&p, m_position.x, m_position.y, m_position.z);
  234.     D3DXMatrixRotationYawPitchRoll(&r, m_rotation.y, m_rotation.x, m_rotation.z);
  235.     D3DXMatrixScaling(&s, m_scale.y, m_scale.x, m_scale.z);
  236.     return s * r * p;
  237. }
  238.  
  239. void UNIT::MoveTo(INTPOINT mp, bool considerUnits, bool _finalGoal)
  240. {
  241.     if(m_pTerrain == NULL)return;
  242.  
  243.     if(_finalGoal)m_finalGoal = mp;
  244.  
  245.     if(m_moving)
  246.     {
  247.         m_path.clear();
  248.         m_path.push_back(m_mappos);
  249.         m_activeWP = 0;
  250.         m_moving = true;
  251.         SetAnimation("Run");
  252.         return;
  253.     }
  254.  
  255.     m_path = m_pTerrain->GetPath(m_mappos, mp, considerUnits);
  256.     
  257.     if(m_path.size() > 0)
  258.     {
  259.         m_moving = true;
  260.  
  261.         if(!CheckCollision(m_path[0]))
  262.         {            
  263.             m_activeWP = 0;
  264.             MoveUnit(m_path[0]);                
  265.             SetAnimation("Run");                
  266.         }
  267.     }
  268.     else m_moving = false;
  269. }
  270.  
  271. void UNIT::MoveUnit(INTPOINT to)
  272. {
  273.     m_lastWP = m_pTerrain->GetWorldPos(m_mappos);
  274.     m_rotation = GetDirection(m_mappos, to);
  275.  
  276.     MAPTILE *tile = m_pTerrain->GetTile(m_mappos);
  277.     if(tile != NULL)tile->m_pMapObject = NULL;
  278.  
  279.     m_mappos = to;    //New m_mappos
  280.     m_movePrc = 0.0f;
  281.     m_nextWP = m_pTerrain->GetWorldPos(m_mappos);
  282.  
  283.     tile = m_pTerrain->GetTile(m_mappos);
  284.     if(tile != NULL)tile->m_pMapObject = this;
  285. }
  286.  
  287. D3DXVECTOR3 UNIT::GetDirection(INTPOINT p1, INTPOINT p2)
  288. {
  289.     int dx = p2.x - p1.x, dy = p2.y - p1.y;
  290.     
  291.     if(dx < 0 && dy > 0)    return D3DXVECTOR3(0.0f, D3DX_PI/4,        0.0f); 
  292.     if(dx == 0 && dy > 0)    return D3DXVECTOR3(0.0f, 0.0f,            0.0f);
  293.     if(dx > 0 && dy > 0)    return D3DXVECTOR3(0.0f, -D3DX_PI/4,    0.0f); 
  294.     if(dx > 0 && dy == 0)    return D3DXVECTOR3(0.0f, -D3DX_PI/2,    0.0f);
  295.     if(dx > 0 && dy < 0)    return D3DXVECTOR3(0.0f, (-D3DX_PI/4)*3,0.0f); 
  296.     if(dx == 0 && dy < 0)    return D3DXVECTOR3(0.0f, D3DX_PI,        0.0f);
  297.     if(dx < 0 && dy < 0)    return D3DXVECTOR3(0.0f, (D3DX_PI/4)*3,    0.0f); 
  298.     if(dx < 0 && dy == 0)    return D3DXVECTOR3(0.0f, D3DX_PI/2,        0.0f);
  299.  
  300.     return m_rotation;
  301. }
  302.  
  303. void UNIT::SetAnimation(char name[])
  304. {
  305.     ID3DXAnimationSet *anim = NULL;
  306.     m_animation = 0;
  307.  
  308.     for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
  309.     {
  310.         anim = NULL;
  311.         m_pAnimControl->GetAnimationSet(i, &anim);
  312.  
  313.         if(anim != NULL)
  314.         {
  315.             if(strcmp(name, anim->GetName()) == 0)
  316.             {
  317.                 m_pAnimControl->ResetTime();
  318.                 m_pAnimControl->SetTrackAnimationSet(0, anim);
  319.                 m_animation = i;
  320.             }
  321.             anim->Release();
  322.         }
  323.     }
  324. }
  325.  
  326. void UNIT::SetAnimation(int index)
  327. {
  328.     ID3DXAnimationSet *anim = NULL;
  329.     m_pAnimControl->GetAnimationSet(index, &anim);
  330.     if(anim != NULL)m_pAnimControl->SetTrackAnimationSet(0, anim);
  331.     anim->Release();
  332. }